package com.example.backstage.config;

import ch.qos.logback.core.util.StringUtil;
import com.example.backstage.entity.Result;
import com.example.backstage.filter.JwtAuthorizeFilter;
import com.example.backstage.util.RedisClient;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.LogoutConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.DelegatingLogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;


@Configuration
public class SecurityConfig {
    @Autowired
    ObjectMapper objectMapper;

    @Autowired
    JwtAuthorizeFilter jwtAuthorizeFilter;

    @Autowired
    RedisClient redisClient;

    /**
     *  配置密码解析器
     * @return BCryptPasswordEncoder
     */
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    /**
     *  认证管理器
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http.authorizeHttpRequests((request)->{

                request.requestMatchers("/login").permitAll();
                request.anyRequest().authenticated();
        });


        http.cors(cors->{
            CorsConfiguration corsConfiguration = new CorsConfiguration();
            //给本地前端项目访问权限
//            corsConfiguration.addAllowedOrigin("http://127.0.0.1:5173");
            //允许所有连接
            corsConfiguration.addAllowedOriginPattern("*");
            corsConfiguration.setAllowCredentials(false);
            corsConfiguration.addAllowedHeader("*");
            corsConfiguration.addAllowedMethod("*");
            corsConfiguration.addExposedHeader("*");
            UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
            source.registerCorsConfiguration("/**",corsConfiguration);
            cors.configurationSource(source);
        });
        /*
          session不发送
         */
        http.sessionManagement(session -> {
            session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        });
        http.csrf(AbstractHttpConfigurer::disable);

        /**
         * 无权限请求
         */
        http.exceptionHandling(httpSecurityExceptionHandlingConfigurer -> {
            httpSecurityExceptionHandlingConfigurer.authenticationEntryPoint((request, response, authException) -> {
                response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                response.setContentType("application/json");
                response.getWriter().println(objectMapper.writeValueAsString(Result.err("无权限")));
            });
        });

        http.addFilterBefore(jwtAuthorizeFilter, UsernamePasswordAuthenticationFilter.class);


        http.logout((Customizer<LogoutConfigurer<HttpSecurity>>) httpSecurityLogoutConfigurer -> {
            httpSecurityLogoutConfigurer.logoutSuccessHandler((request, response, authentication) -> {
                String token = request.getHeader("token");
                if (StringUtil.notNullNorEmpty(token)) {
                    String key = "login:token:" + token;
                    redisClient.del(key);
                    // 可能需要设置编码格式
                    response.setCharacterEncoding(StandardCharsets.UTF_8.name());
                    response.setContentType("application/json");

                    PrintWriter writer = response.getWriter();
                    writer.println(objectMapper.writeValueAsString(Result.ok("注销成功")));
                }
            });
            httpSecurityLogoutConfigurer.logoutUrl("/logout");
        });
        return http.build();
    }
}
